
package com.jic.interaction.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jic.interaction.common.enums.RedisKey;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * http请求通用类
 *
 * @author Administrator
 */
@Component
public class HttpClientUtil {

    @Autowired
    private RedisService redisService;

    @Value("${wz.appid}")
    private String appid;

    @Value("${wz.secret}")
    private String secret;

    private static final Log log = LogFactory.getLog(HttpClientUtil.class.getName());

    public HttpClientUtil() {}

    public static String doRequestGet(String url, Map<String, String> params, Map<String, String> headers) throws IOException, ExecutionException, InterruptedException {
        AsyncHttpClient http = new AsyncHttpClient();
        AsyncHttpClient.BoundRequestBuilder builder = http.prepareGet(url);
        builder.setBodyEncoding("UTF-8");
        Set keys;
        Iterator var6;
        String key;
        if (params != null && !params.isEmpty()) {
            keys = params.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addQueryParameter(key,  String.valueOf(params.get(key)));
            }
        }else{
            log.debug("=====【HttpClientUtils】入参params为空=====");
        }

        if (headers != null && !headers.isEmpty()) {
            keys = headers.keySet();
            var6 = keys.iterator();
            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addHeader(key, String.valueOf(headers.get(key)));
            }
        }

        Future<Response> f = builder.execute();
        String body = (f.get()).getResponseBody("UTF-8");
        System.out.println(body);
        http.close();
        return body;
    }

    public static String doRequestPost(String url, Map<String, String> params, Map<String, String> headers) throws IOException, ExecutionException, InterruptedException {
        log.info("请求地址: " + url);
        log.info("请求参数: " + params);
        AsyncHttpClient http = new AsyncHttpClient();
        AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
        builder.setBodyEncoding("UTF-8");
        Set keys;
        Iterator var6;
        String key;
        if (params != null && !params.isEmpty()) {
            keys = params.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addParameter(key, String.valueOf(params.get(key)));
            }
        }

        if (headers != null && !headers.isEmpty()) {
            keys = headers.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = String.valueOf(var6.next());
                builder.addHeader(key, String.valueOf(headers.get(key)));
            }
        }

        Future<Response> f = builder.execute();
        String body = (f.get()).getResponseBody("UTF-8");
        log.info("响应结果："+body);
        http.close();
        return body;
    }

    public static String doRequestPostObj(String url, Map<String, Object> params, Map<String, Object> headers) throws IOException, ExecutionException, InterruptedException {
        log.info("请求地址: " + url);
        log.info("请求参数: " + params);
        AsyncHttpClient http = new AsyncHttpClient();
        AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
        builder.setBodyEncoding("UTF-8");
        Set keys;
        Iterator var6;
        String key;
        if (params != null && !params.isEmpty()) {
            keys = params.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addParameter(key, (String) params.get(key));
            }
        }

        if (headers != null && !headers.isEmpty()) {
            keys = headers.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addHeader(key, (String) headers.get(key));
            }
        }

        Future<Response> f = builder.execute();
        String body = (f.get()).getResponseBody("UTF-8");
        http.close();
        return body;
    }


    public static String doRequestPostStr(String url, String param,Map<String, Object> headers) throws IOException, ExecutionException, InterruptedException {
        log.info("请求地址: " + url);
        log.info("请求参数: " + param);
        AsyncHttpClient http = new AsyncHttpClient();
        AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
        builder.setBodyEncoding("UTF-8");
        builder.setBody(param);
        Set keys;
        Iterator var6;
        String key;
        if (headers != null && !headers.isEmpty()) {
            keys = headers.keySet();
            var6 = keys.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                builder.addHeader(key, (String) headers.get(key));
            }
        }
        Future<Response> f = builder.execute();
        String body = (f.get()).getResponseBody("UTF-8");
        http.close();
        return body;
    }



    /*
        声明对象 初始化 方便调用依赖
     */

    public static HttpClientUtil httpClientUtil;

    @PostConstruct
    public void init(){
        httpClientUtil = this;
        httpClientUtil.redisService = this.redisService;
    }
    /*
        请求路径 请求体
        jsonData：业务字段，String类型的 json；
     */
    public static String requestPath(String url, Map<String, String> headers,String jsonData) throws IOException, ExecutionException, InterruptedException {

        String res;
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        long ts = date.getTime();
        res = String.valueOf(ts);

        Random rand = new Random();
        StringBuffer sb=new StringBuffer();
        for (int i=1;i<=32;i++){
            int randNum = rand.nextInt(9)+1;
            String num=randNum+"";
            sb=sb.append(num);
        }
        String random=String.valueOf(sb);
        String version = "1.0.0";
        String accessToken = httpClientUtil.redisService.getValue(RedisKey.WZ_SING_TICKET);
        List<String> list = new ArrayList<>();
        list.add(httpClientUtil.appid);
        list.add(random);
        list.add(jsonData);
        list.add(version);
        String sign = sign(list, accessToken);

        url+="?appid="+httpClientUtil.appid + "&nonce=" + random + "&ticketId="+ accessToken + "&timestamp=" + res + "&sign=" + sign + "&version=" + version;
        System.out.println(jsonData);

        return HttpClientUtil.doRequestPostStr2(url,jsonData);
    }
    /*
        加密生成秘钥
     */
    public static String sign(List<String> values, String signTicket) {
        if (values == null) {
            throw new NullPointerException("values为空");
        }
        values.removeAll(Collections.singleton(null));
        values.add(signTicket);
        java.util.Collections.sort(values);
        StringBuilder sb = new StringBuilder();
        for (String s : values) {
            sb.append(s);
        }
        try {
            MessageDigest md = MessageDigest.getInstance("sha1");
            md.update(sb.toString().getBytes("UTF-8"));
            String sign = bytesToHex(md.digest());
            return sign;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /*
        将字符数组转换为字符串
     */
    private static String bytesToHex(byte[] digest) {
        String join = StringUtils.join(digest);
        return join;
    }


    public static String doRequestPostStr2(String url, String param){
        String body = "";
        try {
            SSLContext sslcontext = createIgnoreVerifySSL();
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", new SSLConnectionSocketFactory(sslcontext))
                    .build();
            PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            HttpClients.custom().setConnectionManager(connManager);
            //创建自定义的httpclient对象
            CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
            //创建post方式请求对象
            HttpPost httpPost = new HttpPost(url);


            //指定报文头Content-type、User-Agent
            httpPost.setHeader("Content-type", "application/json");

            httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");

            StringEntity postingString = new StringEntity(param);// json传递
            httpPost.setEntity(postingString);
            //执行请求操作，并拿到结果（同步阻塞）
            CloseableHttpResponse response = client.execute(httpPost);

            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "UTF-8");
            }
            EntityUtils.consume(entity);
            //释放链接
            response.close();
            System.out.println("body:" + body);
        }catch (Exception e){
            e.printStackTrace();
        }
        return body;
    }

    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("SSLv3");

        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sc.init(null, new TrustManager[] { trustManager }, null);
        return sc;
    }

    /**
     * @Author: Puxigui
     * @param: url 请求路径
     * @param param 参数
     * @Description:  微常准
     * @Date: 18:02 2020/11/25
    */
    public static String doRequestWczPost(String url, Map<String,Object> param) {
        System.out.println(JSON.toJSONString(param));
        HttpPost httpPost = null;
        String result = null;
        try {
            HttpClient client = new DefaultHttpClient();
//            httpPost = new HttpPost(chinaPostUrl+url);
            httpPost = new HttpPost("http://139.217.228.165:8070/"+url);
            if (param != null) {
                StringEntity se = new StringEntity(JSON.toJSONString(param), "utf-8");
                // post方法中，加入json数据
                httpPost.setEntity(se);
                httpPost.setHeader("Content-Type", "application/json");
            }
            HttpResponse response = client.execute(httpPost);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, "utf-8");
                }
            }
        } catch (Exception ex) {
            log.error("发送到接口出错", ex);
        }
        return result;
    }

    /**
     * 发送json POST 使用这个,会按照合理的josn格式发送到服务器,不会改变数据类型
     * 直接使用io PrintWriter输出json字符串即可,暂时先这么用,后期可以改为连接池
     * @param url
     * @param param
     * @return
     */
    public static String sendJsonPost(String url,String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            //暂时先不用
            HttpURLConnection httpUrlConnection = (HttpURLConnection) conn;
            //设置json格式
            conn.setRequestProperty("Content-Type", "application/json");
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            //连接超时时间
            conn.setConnectTimeout(200000);
            //读取超时时间
            conn.setReadTimeout(200000);
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
}

